#pragma once
#include "Comm.h"
#if !defined(_USING_V110_SDK71_) && (_WIN32_WINNT >= 0x0600)
#include <synchapi.h>
#endif

namespace COMM
{
	class COMM_API ThreadNullLock
	{
	public:
		virtual ~ThreadNullLock(void);
		virtual void Lock();
		virtual void UnLock();
	};

	class COMM_API ThreadLockGuard
	{
	public:
		ThreadLockGuard(ThreadNullLock* lock);
		~ThreadLockGuard(void);

	private:
		ThreadNullLock* m_lock;
	};

	class COMM_API ThreadLock : public ThreadNullLock
	{
		MYLIB_NONCOPIED_CLASS(ThreadLock);
	public:
		ThreadLock(void);
		~ThreadLock(void);
		
		virtual void Lock();
		virtual void UnLock();
	private:
#ifdef COMM_MSVC
		CRITICAL_SECTION m_cs;
#else
		pthread_mutex_t m_mutex;
#endif
	};
	
	class COMM_API ThreadFreeLock : public ThreadNullLock
	{
		MYLIB_NONCOPIED_CLASS(ThreadFreeLock);
	public:
		ThreadFreeLock(void);
		
		virtual void Lock();
		virtual void UnLock();
	private:
		volatile int m_threadid;
		volatile int m_lockcount;
	};



#if (!defined(_USING_V110_SDK71_) && (_WIN32_WINNT >= 0x0600)) || defined(__GNUC__) //Windows Vista

	// NON-recursion
	//
	class COMM_API ThreadRWLock
	{
		MYLIB_NONCOPIED_CLASS(ThreadRWLock);
	public:
		ThreadRWLock(void);
		~ThreadRWLock(void);

		virtual void Lock(bool read = true);
		virtual void UnLock(bool read = true);
		virtual bool TryLock(bool read = true);
	private:
#ifdef COMM_MSVC
		SRWLOCK m_lock;
#else
		pthread_rwlock_t m_lock;
#endif
	};

	class COMM_API ThreadRWLockGuard
	{
	public:
		ThreadRWLockGuard(ThreadRWLock* lock, bool read = true);
		~ThreadRWLockGuard(void);
	private:
		ThreadRWLock* m_lock;
		bool m_read;
	};

	class COMM_API ThreadReadLockGuard : public ThreadRWLockGuard
	{
	public:
		ThreadReadLockGuard(ThreadRWLock* lock) :ThreadRWLockGuard(lock, true) {}
	};

	class COMM_API ThreadWriteLockGuard : public ThreadRWLockGuard
	{
	public:
		ThreadWriteLockGuard(ThreadRWLock* lock) :ThreadRWLockGuard(lock, false) {}
	};


#else	//XP not support SRWLOCK.
	typedef ThreadLock ThreadRWLock;
	typedef ThreadLockGuard ThreadReadLockGuard;
	typedef ThreadLockGuard ThreadWriteLockGuard;
#endif

}





